package cc.ilzy.mall.user.service.impl;

import cc.ilzy.mall.constants.CommonConstants;
import cc.ilzy.mall.exceptions.ExceptionEnum;
import cc.ilzy.mall.exceptions.MallException;
import cc.ilzy.mall.user.constants.Constants;
import cc.ilzy.mall.user.service.IMailService;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class NotifyServiceImpl implements INotifyService {
    @Autowired
    private IMailService mailService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    /**
     * 前置: 判断是否重复发送
     * 1. 存储验证码到缓存
     * 2. 发送验证码至邮箱或者手机
     * 后置: 存储发送记录
     *
     * 验证码_当前的时间戳
     *
     * @param sendCodeEnum
     * @param to
     */
    @Override
    public void sendCode(CommonConstants.SendCodeEnum sendCodeEnum, String to) {
        // 发送一个验证码, 验证码的存在redis中key code:1:111888334@qq.com
        String  cacheKey = String.format(CommonConstants.CacheKey.CHECK_CODE_KEY, sendCodeEnum.getCode(), to);
        // 发送一个验证码, 验证码的value
        String cacheValue = stringRedisTemplate.opsForValue().get(cacheKey);
        // 如果不为空,则判断是否60秒内重复发送
        if(StrUtil.isNotBlank(cacheValue)){
            // 获取当前时间戳
            long currentTime = System.currentTimeMillis();
            // 获取上次发送的时间戳
            long lastSendTime = Long.parseLong(cacheValue.split("_")[1]);
            // 如果当前时间与上次发送时间小于60秒,则抛出异常
            if(currentTime - lastSendTime < 60 * 1000){
                log.info("请勿重复发送验证码, 当前时间: {}, 上次发送时间: {}", currentTime, lastSendTime);
                throw new MallException(ExceptionEnum.CODE_LIMITED);
            }
        }
        // 生成一个6位随机验证码
        String code = RandomUtil.randomString(6);
        String value = code + "_" + System.currentTimeMillis();
        // 将验证码存入缓存, 设置过期时间为5分钟
        stringRedisTemplate.opsForValue().set(cacheKey, value, 5, TimeUnit.MINUTES);

        // 检查接收人邮件地址格式或者手机号格式并发送验证码
        if(Validator.isMobile(to)) {
            // 发送短信验证码
            log.info("发送短信验证码: {}, 接收人: {}", code, to);
        }else if (Validator.isEmail(to)) {
            // 发送邮件验证码
            log.info("发送邮件验证码: {}, 接收人: {}", code, to);
            mailService.sendMail(to, Constants.MAIL_SUBJECT, String.format(Constants.MAIL_CONTENT, code));
        } else {
            log.error("接收人格式不正确: {}", to);
            throw new RuntimeException("接收人格式不正确");
        }

    }

    @Override
    public void checkCode(CommonConstants.SendCodeEnum sendCodeEnum, String to, String code) {
        // 发送一个验证码, 验证码的存在redis中key code:1:111888334@qq.com
        String  cacheKey = String.format(CommonConstants.CacheKey.CHECK_CODE_KEY, sendCodeEnum.getCode(), to);
        // 发送一个验证码, 验证码的value
        String cacheValue = stringRedisTemplate.opsForValue().get(cacheKey);
        // 如果不为空,则判断是否60秒内重复发送
        if(StrUtil.isNotBlank(cacheValue)){
            // 获取验证码和时间戳
            String value = cacheValue.split("_")[0];
            if( StrUtil.equals(value, code)) {
                // 验证码正确, 删除缓存
                stringRedisTemplate.delete(cacheKey);
                log.info("验证码验证成功, 接收人: {}, 验证码: {}", to, code);
                return;
            }
        }
        // 如果为空,则抛出异常
        log.error("验证码不正确, 接收人: {}, 验证码: {}, 缓存值: {}", to, code, cacheValue);
        throw new MallException(ExceptionEnum.CODE_ERROR);
    }
}






























